package cn.xiaolang.thread.threadlocal;

import com.alibaba.ttl.TransmittableThreadLocal;
import com.alibaba.ttl.TtlRunnable;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 父子线程传值(阿里封装了一个工具，实现了在使用线程池等会池化复用线程的组件情况下，提供ThreadLocal值的传递功能，解决异步执行时上下文传递的问题)
 *
 * @author Dean
 * @date 2021-01-20
 * @see { https:ø//github.com/alibaba/transmittable-thread-local }
 */
@Slf4j
public class ParentChildPassValueIssueSolve3 {

    private static final ExecutorService executorService = Executors.newSingleThreadExecutor();

    private static final TransmittableThreadLocal<TargetUser> parent = new TransmittableThreadLocal<>();

    public static void main(String[] args) {
        parent.set(new TargetUser("dean-parent"));

        // 额外的处理，生成修饰了的对象ttlRunnable；子线程可以直接读取父线程设定的值
        executorService.submit(Objects.requireNonNull(TtlRunnable.get(new ChildThread("task1"))));

        // Task中可以读取，值是"dean-parent"
        log.info(" parent thread get result:{}", parent.get());
        executorService.shutdown();
    }

    static class ChildThread implements Runnable {

        private final String taskName;

        public ChildThread(String taskName) {
            this.taskName = taskName;
        }

        @Override
        public void run() {

            //如果启用了线程（调用start方法），调用get方法是获取不到值的
            TargetUser originVal = parent.get();
            log.info("child get from parent directly:{}", originVal);

            // 修改从父线程获取到的值
            originVal.setName("dean-child" + taskName);
        }
    }

    @Data
    @AllArgsConstructor
    private static class TargetUser {

        private String name;

    }
}


